package com.efamily.ewallet.client.account;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import com.efamily.ewallet.client.account.bean.AccountBean;
import com.efamily.ewallet.client.account.bean.AccountSearchConfig;
import com.efamily.ewallet.client.account.service.AccountManagerServiceAsync;
import com.efamily.ewallet.client.common.CustomEventType;
import com.efamily.ewallet.client.common.CustomEvents;
import com.efamily.ewallet.client.common.DifferentItemsSummaryRenderer;
import com.extjs.gxt.ui.client.data.BasePagingLoader;
import com.extjs.gxt.ui.client.data.BeanModel;
import com.extjs.gxt.ui.client.data.BeanModelReader;
import com.extjs.gxt.ui.client.data.PagingLoadConfig;
import com.extjs.gxt.ui.client.data.PagingLoadResult;
import com.extjs.gxt.ui.client.data.PagingLoader;
import com.extjs.gxt.ui.client.data.RpcProxy;
import com.extjs.gxt.ui.client.event.BaseEvent;
import com.extjs.gxt.ui.client.event.ButtonEvent;
import com.extjs.gxt.ui.client.event.Events;
import com.extjs.gxt.ui.client.event.Listener;
import com.extjs.gxt.ui.client.event.SelectionChangedEvent;
import com.extjs.gxt.ui.client.event.SelectionChangedListener;
import com.extjs.gxt.ui.client.event.SelectionListener;
import com.extjs.gxt.ui.client.mvc.Dispatcher;
import com.extjs.gxt.ui.client.store.GroupingStore;
import com.extjs.gxt.ui.client.widget.Composite;
import com.extjs.gxt.ui.client.widget.ContentPanel;
import com.extjs.gxt.ui.client.widget.MessageBox;
import com.extjs.gxt.ui.client.widget.button.Button;
import com.extjs.gxt.ui.client.widget.grid.ColumnConfig;
import com.extjs.gxt.ui.client.widget.grid.ColumnModel;
import com.extjs.gxt.ui.client.widget.grid.Grid;
import com.extjs.gxt.ui.client.widget.grid.GridGroupRenderer;
import com.extjs.gxt.ui.client.widget.grid.GroupColumnData;
import com.extjs.gxt.ui.client.widget.grid.GroupSummaryView;
import com.extjs.gxt.ui.client.widget.grid.SummaryColumnConfig;
import com.extjs.gxt.ui.client.widget.grid.SummaryRenderer;
import com.extjs.gxt.ui.client.widget.layout.FitLayout;
import com.extjs.gxt.ui.client.widget.toolbar.PagingToolBar;
import com.extjs.gxt.ui.client.widget.toolbar.SeparatorToolItem;
import com.extjs.gxt.ui.client.widget.toolbar.ToolBar;
import com.google.gwt.user.client.rpc.AsyncCallback;

public class PublicAccountGridWidget extends Composite {
	private Grid<BeanModel> grid;
	private AccountSearchConfig searchConfig;
	private ContentPanel contentPanel = new ContentPanel();
	private int rowCount = 40;
	private final AccountManagerServiceAsync accountManagerService = AccountManagerServiceAsync.instance;

	public PublicAccountGridWidget() {
		buildGrid();
		initComponent(contentPanel);
	}

	private void buildGrid() {
		RpcProxy<PagingLoadResult<AccountBean>> proxy = new RpcProxy<PagingLoadResult<AccountBean>>() {
			@Override
			protected void load(Object loadConfig,
					AsyncCallback<PagingLoadResult<AccountBean>> callback) {
				accountManagerService.getPublicAccountList(searchConfig,
						(PagingLoadConfig) loadConfig, callback);
			}
		};

		PagingLoader<PagingLoadResult<BeanModel>> loader = new BasePagingLoader<PagingLoadResult<BeanModel>>(
				proxy, new BeanModelReader());
		loader.setRemoteSort(true);
		PagingToolBar pagingToolBar = new PagingToolBar(rowCount);
		pagingToolBar.bind(loader);
		contentPanel.setBottomComponent(pagingToolBar);
		GroupingStore<BeanModel> store = new GroupingStore<BeanModel>(loader);

		store.groupBy("country");
		List<ColumnConfig> columns = new ArrayList<ColumnConfig>();
		SummaryColumnConfig<Integer> id = new SummaryColumnConfig<Integer>(
				"id", "Identifier", 35);
		id.setHidden(true);
		id.setGroupable(false);
		SummaryColumnConfig<Integer> nickName = new SummaryColumnConfig<Integer>(
				"nickName", "Nick Name", 50);
		nickName.setGroupable(false);
		SummaryColumnConfig<Integer> balance = new SummaryColumnConfig<Integer>(
				"balance", "Balance", 50);
		balance.setGroupable(false);
		// TODO group by some range
		SummaryColumnConfig<Integer> gender = new SummaryColumnConfig<Integer>(
				"gender", "Gender", 50);
		gender.setSummaryType(new DifferentItemsSummaryRenderer());
		gender.setSummaryRenderer(new SummaryRenderer() {
			public String render(Number value, Map<String, Number> data) {
				return value.intValue() > 1 ? "(Men and Women)"
						: "(Folk are the same gender)";
			}
		});
		SummaryColumnConfig<Integer> age = new SummaryColumnConfig<Integer>(
				"age", "Age", 50);
		// TODO create age groping
		/*
		 * category.setSummaryType(new DifferentItemsSummaryRenderer());
		 * category.setSummaryRenderer(new SummaryRenderer() { public String
		 * render(Number value, Map<String, Number> data) { return
		 * value.intValue() > 1 ? "(In " + value.intValue() + " Categories)" :
		 * "(In 1 Category)"; } });
		 */
		SummaryColumnConfig<Integer> occupation = new SummaryColumnConfig<Integer>(
				"occupation", "Occupation", 50);
		// weekDay.setHidden(true);
		/*
		 * weekDay.setSummaryType(new DifferentItemsSummaryRenderer());
		 * weekDay.setSummaryRenderer(new SummaryRenderer() { public String
		 * render(Number value, Map<String, Number> data) { return
		 * value.intValue() > 1 ? "(In" + value.intValue() + " Days)" :
		 * "(In 1 Day)"; } });
		 */
		SummaryColumnConfig<Integer> country = new SummaryColumnConfig<Integer>(
				"country", "Country", 50);
		country.setSummaryType(new DifferentItemsSummaryRenderer());
		country.setSummaryRenderer(new SummaryRenderer() {
			public String render(Number value, Map<String, Number> data) {
				return value.intValue() > 1 ? "(In " + value.intValue()
						+ " countries)" : "(In 1 country)";
			}
		});
		columns.add(id);
		columns.add(nickName);
		columns.add(balance);
		columns.add(occupation);
		columns.add(country);
		columns.add(gender);
		columns.add(age);

		final ColumnModel cm = new ColumnModel(columns);

		GroupSummaryView view = new GroupSummaryView();
		view.setShowGroupedColumn(false);
		view.setForceFit(true);
		view.setGroupRenderer(new GridGroupRenderer() {
			public String render(GroupColumnData data) {
				String f = cm.getColumnById(data.field).getHeader();
				String l = data.models.size() == 1 ? "Item" : "Items";
				return f + ": " + data.group + " (" + data.models.size() + " "
						+ l + ")";
			}
		});

		contentPanel.setHeaderVisible(false);
		contentPanel.setLayout(new FitLayout());

		grid = new Grid<BeanModel>(store, cm);
		grid.setView(view);
		grid.setBorders(true);
		grid.setAutoExpandColumn("age");
		//grid.setMinColumnWidth(40);
		grid.setStripeRows(true);
		grid.addListener(Events.RowDoubleClick, new Listener<BaseEvent>() {
			public void handleEvent(BaseEvent be) {
				List<BeanModel> accounts = grid.getSelectionModel()
						.getSelectedItems();
				Dispatcher.get().fireEvent(CustomEvents.SHOW_USER_BUSINESS.getEventType(), new BaseEvent(accounts));
			}
		});
		contentPanel.add(grid);

		addToolbar();
	}

	private void addToolbar() {
		ToolBar toolBar = new ToolBar();
		final Button addBtn = new Button("&nbsp;Create New Account");
		addBtn.setIconStyle("icon-add");
		addBtn.addSelectionListener(new SelectionListener<ButtonEvent>() {
			@Override
			public void componentSelected(ButtonEvent ce) {
				RegisterAccountWindow.getInstance().show();
			}
		});
		final Button walletBtn = new Button("&nbsp;Show User Wallet");
		walletBtn.setIconStyle("icon-wallet");
		walletBtn.setEnabled(false);
		walletBtn.addSelectionListener(new SelectionListener<ButtonEvent>() {
			@Override
			public void componentSelected(ButtonEvent ce) {
				List<BeanModel> accounts = grid.getSelectionModel()
						.getSelectedItems();
				Dispatcher.get().fireEvent(CustomEvents.SHOW_USER_BUSINESS.getEventType(), new BaseEvent(accounts));
			}
		});
		final Button userDetailsBtn = new Button("&nbsp;Show User Details");
		userDetailsBtn.setIconStyle("icon-user-info");
		userDetailsBtn.setEnabled(false);
		userDetailsBtn.addSelectionListener(new SelectionListener<ButtonEvent>() {
			@Override
			public void componentSelected(ButtonEvent ce) {
				MessageBox.alert("Warning!", "Not Implemented", null);
				List<BeanModel> accounts = grid.getSelectionModel()
						.getSelectedItems();
				Dispatcher.get().fireEvent(CustomEvents.SHOW_USER_DETAILS.getEventType(), new BaseEvent(accounts));
			}
		});
		toolBar.add(addBtn);
		toolBar.add(new SeparatorToolItem());
		toolBar.add(walletBtn);
		toolBar.add(new SeparatorToolItem());
		toolBar.add(userDetailsBtn);
		contentPanel.setTopComponent(toolBar);

		grid.getSelectionModel().addSelectionChangedListener(
				new SelectionChangedListener<BeanModel>() {
					@Override
					public void selectionChanged(
							SelectionChangedEvent<BeanModel> se) {
						if (se.getSelection().size() == 0) {
							walletBtn.setEnabled(false);
							userDetailsBtn.setEnabled(false);
						} else {
							walletBtn.setEnabled(true);
							userDetailsBtn.setEnabled(true);
						}
					}
				});
	}

	@SuppressWarnings("unchecked")
	@Override
	protected void onLoad() {
		super.onLoad();
		((PagingLoader) grid.getStore().getLoader()).load(0, rowCount);
	}

	public int getRowCount() {
		return rowCount;
	}

	public void setRowCount(int rowCount) {
		this.rowCount = rowCount;
		((PagingToolBar) contentPanel.getBottomComponent())
				.setPageSize(rowCount);
	}

}
